/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.ucuenca.ec.nosql.conexion;

import edu.ucuenca.ec.nosql.modelos.Persona;
import edu.ucuenca.ec.nosql.modelos.TipoRelacion;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 *
 * @author mivkys
 */
public class Neo4jEngine {

    private static GraphDatabaseService db;

    public static void conexionFactory() {
        GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
        db = dbFactory.newEmbeddedDatabase("/Users/mivkys/Documents/test");
    }

    public static void crearVariosNodos(List<Persona> amigos) {
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                for (Persona arg : amigos) {
                    Node javaNode = db.createNode(arg);
                    javaNode.setProperty("Id", arg.getId());
                    javaNode.setProperty("username", arg.getUsername());
                    //nodes.add(javaNode);
                    tx.success();
                }
            }
        }
    }

    public static void crearUnNodo(Persona amigo) {
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                Node javaNode = db.createNode(amigo);
                javaNode.setProperty("Id", amigo.getId());
                javaNode.setProperty("username", amigo.getUsername());
                tx.success();
            }
        }
    }

    public static void crearRelacion(Persona persona, Persona amigo) {
        if (!persona.equals(amigo)) {
            Node node = matchUnNodo(persona);
            Node node1 = matchUnNodo(amigo);
            if (db != null) {
                try (Transaction txr = db.beginTx()) {
                    Relationship relationship1 = node.createRelationshipTo(node1, TipoRelacion.AMIGOS);
                    //relationship1.setProperty("Id", "1")
                    txr.success();
                }
            }
        }
    }

    public static void crearRelaciones(Persona persona, List<Persona> amigos) {
        Node node = matchUnNodo(persona);
        List<Node> nodes = matchAlgunosNodos(amigos);
        if (db != null) {
            try (Transaction txr = db.beginTx()) {
                for (Node node1 : nodes) {
                    Relationship relationship1 = node.createRelationshipTo(node1, TipoRelacion.AMIGOS);
                    //relationship1.setProperty("Id", "1");
                }
                txr.success();
            }
        }
    }

    public static List<Node> buscaRelaciones(Persona amigo) {
        List<Node> nodes = new ArrayList<>();
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        try (Transaction ignored = db.beginTx()) {
            String querry = "match (n {Id:" + amigo.getId() + "})--return n.name";
            result = engine.execute(querry);
            Iterator<Node> n_column = result.columnAs("n");
            for (Node node : IteratorUtil.asIterable(n_column)) {
                int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));

                nodes.add(node);

            }
            ignored.success();
        }
        return nodes;
    }

    public static List<Node> matchAlgunosNodos(List<Persona> amigos) {
        List<Node> nodes = new ArrayList<>();
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                for (Persona amigo : amigos) {
                    String querry = "match (n {Id:" + amigo.getId() + "}) return n, n.name";
                    result = engine.execute(querry);
                    Iterator<Node> n_column = result.columnAs("n");
                    for (Node node : IteratorUtil.asIterable(n_column)) {
                        int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
                        if (id == amigo.getId()) {
                            nodes.add(node);
                        }
                    }
                }
                tx.success();
            }
        }
        return nodes;
    }

    public static Node matchUnNodo(Persona amigo) {
        Node nodes = null;
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                String querry = "match (n {Id:" + amigo.getId() + "}) return n, n.name";
                result = engine.execute(querry);
                Iterator<Node> n_column = result.columnAs("n");
                for (Node node : IteratorUtil.asIterable(n_column)) {
                    nodes = node;
                }
                tx.success();
            }
        }
        return nodes;
    }

    public static Persona convertNodo(Node node, List<Persona> personas) {
        int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
        for (Persona persona : personas) {
            if (persona.getId() == id) {
                return persona;
            }
        }
        return null;
    }

    public static List<Persona> convertAllNodo(List<Node> nodes, List<Persona> personas) {
        List<Persona> amigos = new ArrayList<>();
        for (Node node : nodes) {
            int id = Integer.valueOf(String.valueOf(node.getProperty("Id")));
            for (Persona persona : personas) {
                if (persona.getId() == id) {
                    amigos.add(persona);
                    System.out.println("Amigo:"+ persona.getNombres());
                }
            }
        }
        
        return (!amigos.isEmpty()) ? amigos : null;
    }

    public static List<Node> matchAllNodos() {
        List<Node> nodes = new ArrayList<>();
        ExecutionEngine engine = new ExecutionEngine(db);
        ExecutionResult result;
        if (db != null) {
            try (Transaction tx = db.beginTx()) {
                result = engine.execute("MATCH (n) RETURN n ");
                Iterator<Node> n_column = result.columnAs("n");
                for (Node node : IteratorUtil.asIterable(n_column)) {
                    nodes.add(node);
                }
                tx.success();
            }
        }
        return nodes;
    }

    public static void shudownConexion() {
        if (db != null) {
            db.shutdown();
        }
    }
}
